import { appMap } from "./app";

type EventInfo = {
  data: any;
  callback: Set<Function>;
};

/**
 * 数据通讯用
 * <micro-app data={data} @dataChange={fn} />
 */
class EventCenter {
  eventList = new Map<string, EventInfo>();

  on(name: string, fn: Function) {
    let eventInfo = this.getEventInfo(name);
    eventInfo.callback.add(fn);
  }

  dispatch(name: string, data: any) {
    const eventInfo = this.eventList.get(name);
    if (!eventInfo) return;
    if (eventInfo.data === data) return;
    eventInfo.data = data;
    eventInfo.callback.forEach((fn) => fn(data));
  }

  off(name: string, f: Function) {
    let eventInfo = this.eventList.get(name);
    if (!eventInfo) return;
    if (!eventInfo.callback.has(f)) return;
    eventInfo.callback.delete(f);
  }

  private getEventInfo(name: string) {
    let eventInfo = this.eventList.get(name);
    if (!eventInfo) {
      eventInfo = {
        data: {},
        callback: new Set(),
      };

      this.eventList.set(name, eventInfo);
    }

    return eventInfo;
  }
}

const eventCenter = new EventCenter();

export class EventCenterBaseApp {
  setData(appName: string, data: any) {
    eventCenter.dispatch(appName, data);
  }
}

export class EventCenterMicroApp {
  appName: string;
  constructor(appName: string) {
    this.appName = appName;
  }

  addDataListener(fn: Function) {
    eventCenter.on(this.appName, fn);
  }

  dispatch(data: any) {
    const app = appMap.get(this.appName);
    if (!app?.container) return;
    const event = new CustomEvent("dataChange", data);
    app.container.dispatch(event);
  }
}
